package com.demo.sender.notice.dingtalk.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * 将时间戳 timestamp 和密钥 secret 当做签名字符串，使用HmacSHA256算法计算签名，然后进行Base64 encode，最后再把签名参数再进行urlEncode，得到最终的签名（需要使用UTF-8字符集）。
 * <a href="https://open.dingtalk.com/document/robots/customize-robot-security-settings">https://open.dingtalk.com/document/robots/customize-robot-security-settings</a>
 *
 * @author wangfengchen
 */
@Slf4j
public class DingTalkSignUtil {

  /**
   * 签名校验
   *
   * @param secret    密钥，机器人安全设置页面，加签一栏下面显示的SEC开头的字符串。
   * @param timestamp 开发者服务内当前系统时间戳，单位是毫秒，与请求调用时间误差不能超过1小时。
   * @return
   */
  public static String genSign(String secret, int timestamp) {
    if (StringUtils.isBlank(secret)) {
      return null;
    }
    //把timestamp+"\n"+密钥当做签名字符串
    String stringToSign = timestamp + "\n" + secret;
    Mac mac = null;
    try {
      mac = Mac.getInstance("HmacSHA256");
      mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
      byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
      return URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
    } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) {
      log.error("生成签名异常，e = {}", ExceptionUtils.getStackTrace(e));
      throw new RuntimeException(e);
    }
  }

}
